#include "flash.h"
#include "main.h"
#define FLASH_VOLTAGE_RANGE_1        0x00000000U  /* Flash program/erase by 32 bits */
/*
**********************************************************************************************************
*    函 数 名: bsp_EraseCpuFlash
*    功能说明: 擦除CPU FLASH一个扇区 （128KB)
*    形    参: _ulFlashAddr : 某个扇区
*    返 回 值: 0 成功， 1 失败
*              HAL_OK       = 0x00,
*              HAL_ERROR    = 0x01,
*              HAL_BUSY     = 0x02,
*              HAL_TIMEOUT  = 0x03
*
******************************************************************************************************
*/
uint8_t bsp_EraseCpuFlash(uint32_t FirstSector)
{
    uint8_t re;

    /* 解锁 */
    HAL_FLASH_Unlock();

    FLASH_Erase_Sector(FirstSector,FLASH_BANK_1,FLASH_VOLTAGE_RANGE_1);
    /* 擦除完毕后，上锁 */
    HAL_FLASH_Lock();

    return re;
}

/*
.    ******************************************************************************************************
.    *    函 数 名: bsp_WriteCpuFlash
.    *    功能说明: 写数据到CPU 内部Flash。 必须按32字节整数倍写。不支持跨扇区。扇区大小128KB. \
.    *              写之前需要擦除扇区. 长度不是32字节整数倍时，最后几个字节末尾补0写入.
.    *    形    参: _ulFlashAddr : Flash地址
.    *             _ucpSrc : 数据缓冲区
.    *             _ulSize : 数据大小（单位是字节, 必须是32字节整数倍）
.    *    返 回 值: 0-成功，1-数据长度或地址溢出，2-写Flash出错(估计Flash寿命到)
.    ******************************************************************************************************
.    */
uint8_t bsp_WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize)
{
    uint32_t i;
    uint8_t rt = 0;
    /* 如果偏移地址超过芯片容量，则不改写输出缓冲区 */
    if (_ulFlashAddr + _ulSize > FLASH_END)
    {
        return 1;
    }

    /* 长度为0时不继续操作  */
    if (_ulSize == 0)
    {
        return 0;
    }
    __set_PRIMASK(1); /* 关中断 */

    /* FLASH 解锁 */
    HAL_FLASH_Unlock();

    for (i = 0; i < _ulSize / 16; i++)
    {
        uint64_t FlashWord[2];

        memcpy((char *)FlashWord, _ucpSrc, 16);
        _ucpSrc += 16;

        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr,
                              (uint64_t)((uint32_t)FlashWord)) == HAL_OK)
        {
            _ulFlashAddr = _ulFlashAddr + 16; /* 递增，操作下一个256bit */
        }
        else
        {
            rt = 1;
            break;
        }
    }

    /* 长度不是32字节整数倍 */
    if (_ulSize % 16)
    {
        uint64_t FlashWord[2];

        FlashWord[0] = 0;
        FlashWord[1] = 0;
        memcpy((char *)FlashWord, _ucpSrc, _ulSize % 16);
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr,
                              (uint64_t)((uint32_t)FlashWord)) == HAL_OK)
        {
            ; // _ulFlashAddr = _ulFlashAddr + 32;
        }
        else
        {
            rt = 1;
        }
    }

    /* Flash 加锁，禁止写Flash控制寄存器 */
    HAL_FLASH_Lock();

    __set_PRIMASK(0); /* 开中断 */

    return rt;
}

/*
*********************************************************************************************************
*    函 数 名: bsp_ReadCpuFlash
*    功能说明: 读取CPU Flash的内容
*    形    参:  _ucpDst : 目标缓冲区
*             ulFlashAddr : 起始地址
*             _ulSize : 数据大小（单位是字节）
*    返 回 值: 0=成功，1=失败
*********************************************************************************************************
*/
uint8_t bsp_ReadCpuFlash(uint32_t ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize)
{
    uint32_t i;

    if (ulFlashAddr + _ulSize > FLASH_END)
    {
        return 1;
    }

    /* 长度为0时不继续操作,否则起始地址为奇地址会出错 */
    if (_ulSize == 0)
    {
        return 1;
    }

    for (i = 0; i < _ulSize; i++)
    {
        *_ucpDst++ = *(uint8_t *)ulFlashAddr++;
    }

    return 0;
}
